// =================================================================
// -- System Controller
// =================================================================

`timescale 1ns/1ps

module sys_ctrl(
   // Clock and reset
    input clk
   ,input reset_n

   // Function singles
   ,input           vs
   ,output  reg     lvds_vs_pulse
   ,output  reg     vs_pos_pulse

   // Display parameter
   ,output  [11 -1: 0] original_weight
   ,output  [11 -1: 0] original_height
   ,output  [11 -1: 0] scale_weight
   ,output  [11 -1: 0] scale_height
   ,output  vs_polarity
   ,output  hs_polarity
   ,output  [4 -1: 0]   scale_mode
   ,output  [4 -1: 0]   dimension_mode

   // Scaler parameter
   ,output  reg             pwrite
   ,output  reg [5  -1: 0]  paddr
   ,output  reg [32 -1: 0]  pwdat
   ,input       [32 -1: 0]  prdat1
   ,input       [32 -1: 0]  prdat2
   
   // Configure by I2C interface
   ,output  reg [11 -1: 0]  ORIG_HS_PRELOGE
   ,output  reg [11 -1: 0]  ORIG_HS_PULSE  
   ,output  reg [11 -1: 0]  ORIG_HS_EPILOGE
   ,output  reg [11 -1: 0]  ORIG_HS_ACTIVE 
   ,output  reg [12 -1: 0]  ORIG_HS_TOTAL
   ,output  reg [11 -1: 0]  ORIG_VS_PRELOGE
   ,output  reg [11 -1: 0]  ORIG_VS_PULSE
   ,output  reg [11 -1: 0]  ORIG_VS_EPILOGE
   ,output  reg [11 -1: 0]  ORIG_VS_ACTIVE
   ,output  reg [12 -1: 0]  ORIG_VS_TOTAL

   ,output  [11 -1: 0]  SCAL_HS_PRELOGE
   ,output  [11 -1: 0]  SCAL_HS_PULSE  
   ,output  [11 -1: 0]  SCAL_HS_EPILOGE
   ,output  [11 -1: 0]  SCAL_HS_ACTIVE 
   ,output  [12 -1: 0]  SCAL_HS_TOTAL
   ,output  [11 -1: 0]  SCAL_VS_PRELOGE
   ,output  [11 -1: 0]  SCAL_VS_PULSE
   ,output  [11 -1: 0]  SCAL_VS_EPILOGE
   ,output  [11 -1: 0]  SCAL_VS_ACTIVE
   ,output  [12 -1: 0]  SCAL_VS_TOTAL

   // I2C interface
   ,input  wire     scl
   ,input  wire     sda_in
   ,output wire     sda_oe
);

//=======================================================
//  Local parametr 
//=======================================================

// ====================================================================
// Wires & Registers
// ====================================================================
wire                    init_delay_done;
reg                     vs_d;
reg                     vs_d1;
wire                    vs_posPulse;
wire                    vs_negPulse;
reg                     vs_negPulse_d;
reg     [32 -1: 0]      delay_count;
reg                     count_enable;

reg     [4 -1: 0]       pset_enable;
reg     [3 -1: 0]       pset_count;

wire    [8 -1: 0]       input_resoulution;
wire    [8 -1: 0]       output_resoulution;

wire    [8 -1: 0]       spi1_ctrl;
wire    [8 -1: 0]       spi1_addr;
wire    [8 -1: 0]       spi1_wdata;
wire    [8 -1: 0]       spi2_ctrl;
wire    [8 -1: 0]       spi2_addr;
wire    [8 -1: 0]       spi2_wdata;
//===================================================================
//--Display parameter
`ifdef DEBUG
always @ (*) begin
  if (input_resoulution == 8'h01) begin //720P
    ORIG_HS_PRELOGE = 110;
    ORIG_HS_PULSE = 40;
    ORIG_HS_EPILOGE = 220;
    ORIG_HS_ACTIVE = 1280;
    ORIG_HS_TOTAL = 1650;
    ORIG_VS_PRELOGE = 5;
    ORIG_VS_PULSE = 6;
    ORIG_VS_EPILOGE = 4;
    ORIG_VS_ACTIVE = 6;
    ORIG_VS_TOTAL = ORIG_VS_PRELOGE + ORIG_VS_PULSE + ORIG_VS_EPILOGE + ORIG_VS_ACTIVE;
  end else begin //1080P
    ORIG_HS_PRELOGE = 88;
    ORIG_HS_PULSE = 44;
    ORIG_HS_EPILOGE = 148;
    ORIG_HS_ACTIVE = 1920;
    ORIG_HS_TOTAL = 2200;
    ORIG_VS_PRELOGE = 4;
    ORIG_VS_PULSE = 5;
    ORIG_VS_EPILOGE = 4;
    ORIG_VS_ACTIVE = 9;
    ORIG_VS_TOTAL = ORIG_VS_PRELOGE + ORIG_VS_PULSE + ORIG_VS_EPILOGE + ORIG_VS_ACTIVE;
  end
end
`else
always @ (*) begin
  if (input_resoulution == 8'h01) begin //720P
    ORIG_HS_PRELOGE = 110;
    ORIG_HS_PULSE = 40;
    ORIG_HS_EPILOGE = 220;
    ORIG_HS_ACTIVE = 1280;
    ORIG_HS_TOTAL = 1650;
    ORIG_VS_PRELOGE = 5;
    ORIG_VS_PULSE = 6;
    ORIG_VS_EPILOGE = 20;
    ORIG_VS_ACTIVE = 720;
    ORIG_VS_TOTAL = 750;
  end else begin //1080P
    ORIG_HS_PRELOGE = 88;
    ORIG_HS_PULSE = 44;
    ORIG_HS_EPILOGE = 148;
    ORIG_HS_ACTIVE = 1920;
    ORIG_HS_TOTAL = 2200;
    ORIG_VS_PRELOGE = 4;
    ORIG_VS_PULSE = 5;
    ORIG_VS_EPILOGE = 36;
    ORIG_VS_ACTIVE = 1080;
    ORIG_VS_TOTAL = 1125;
  end
end
`endif

`ifdef DEBUG
assign SCAL_HS_PRELOGE = 88;
assign SCAL_HS_PULSE = 44;
assign SCAL_HS_EPILOGE = 148;
assign SCAL_HS_ACTIVE = 1920;
assign SCAL_HS_TOTAL = 2200;
assign SCAL_VS_PRELOGE = 4;
assign SCAL_VS_PULSE = 5;
assign SCAL_VS_EPILOGE = 4;
assign SCAL_VS_ACTIVE = 9;
assign SCAL_VS_TOTAL = SCAL_VS_PRELOGE + SCAL_VS_PULSE + SCAL_VS_EPILOGE + SCAL_VS_ACTIVE;
`else
assign SCAL_HS_PRELOGE = 88;
assign SCAL_HS_PULSE = 44;
assign SCAL_HS_EPILOGE = 148;
assign SCAL_HS_ACTIVE = 1920;
assign SCAL_HS_TOTAL = 2200;
assign SCAL_VS_PRELOGE = 4;
assign SCAL_VS_PULSE = 5;
assign SCAL_VS_EPILOGE = 36;
assign SCAL_VS_ACTIVE = 1080;
assign SCAL_VS_TOTAL = 1125;
`endif

assign original_weight = ORIG_HS_ACTIVE;
assign original_height = ORIG_VS_ACTIVE;
assign scale_weight = SCAL_HS_ACTIVE;
assign scale_height = SCAL_VS_ACTIVE;
assign vs_polarity = 1'b1;
assign hs_polarity = 1'b1;

//-- generate the lvds_vs_pulse
always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    vs_d  <= !vs_polarity;
    vs_d1 <= !vs_polarity;
  end else begin
    vs_d  <= vs;
    vs_d1 <= vs_d;
  end
end

assign vs_posPulse = vs_d & (!vs_d1);
assign vs_negPulse = (!vs_d) & vs_d1;
always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    vs_pos_pulse <= 0;
  end else begin
    vs_pos_pulse <= vs_posPulse;
  end
end

always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    count_enable <= 0;
  end else if (vs_posPulse) begin
    count_enable <= 1;
  end
end

always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    delay_count <= 0;
  end else if (vs_posPulse) begin
    delay_count <= 0;
  end else if (count_enable) begin
    delay_count <= delay_count + 1;
  end
end

always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    lvds_vs_pulse <= 0;
  end else if ((dimension_mode == 0) && (scale_mode == 0) //2D, No Scale
            || (dimension_mode == 2) && (scale_mode == 0) //3DO, No Scale
              ) begin 
    if (delay_count == (((SCAL_HS_TOTAL <<1) -1))) begin
      lvds_vs_pulse <= 1;
    end else begin
      lvds_vs_pulse <= 0;
    end
  end else if ((dimension_mode == 1) && (scale_mode == 1) //3DLR, Scale
              ) begin 
    if ((input_resoulution == 8'h00) && (delay_count == ((SCAL_HS_TOTAL <<2) -1))) begin
      lvds_vs_pulse <= 1;
    end else if ((input_resoulution == 8'h01) && (delay_count == (SCAL_HS_TOTAL*11 -1))) begin
      lvds_vs_pulse <= 1;
    end else begin
      lvds_vs_pulse <= 0;
    end
  end else begin //Default Value
    lvds_vs_pulse <= 0;
  end
end

//-- I2C 
i2c_config_reg i2c_csr_inst(
    .clk(clk)
    ,.rstn(reset_n)

    ,.input_resoulution(input_resoulution)
    ,.output_resoulution(output_resoulution)
    ,.scale_mode(scale_mode)
    ,.dimension_mode(dimension_mode)

    ,.spi1_ctrl(spi1_ctrl)
    ,.spi1_addr(spi1_addr)
    ,.spi1_wdata(spi1_wdata)
    ,.spi2_ctrl(spi2_ctrl)
    ,.spi2_addr(spi2_addr)
    ,.spi2_wdata(spi2_wdata)

    ,.scl(scl)
    ,.sda_in(sda_in)
    ,.sda_oe(sda_oe)
);  

assign init_delay_done = lvds_vs_pulse; //config each frame
   
//-- Scaler Configure
always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    pset_enable <= 0;
  end else if (init_delay_done) begin
    pset_enable <= 1;
  end else if (pset_count == 3'h7) begin
    pset_enable <= 0;
  end
end

always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    pset_count <= 0;
  end else if (pset_count == 3'h7) begin
    pset_count <= 0;
  end else if (pset_enable) begin
    pset_count <= pset_count + 1'b1;
  end
end

always@(posedge clk or negedge reset_n)
begin
  if(!reset_n) begin
    pwrite <= 0;
    paddr  <= 0;
    pwdat  <= 0;
  end else if (pset_enable) begin
    case (pset_count)
      3'h0: begin
        pwrite <= 1;
        paddr  <= 5'h00;
        if ((dimension_mode == 1) && (scale_mode == 1)) begin
        	pwdat  <= (ORIG_HS_ACTIVE>>1) -1;
        end else begin
        	pwdat  <= (ORIG_HS_ACTIVE) -1;
        end
      end
      3'h1: begin
        pwrite <= 1;
        paddr  <= 5'h04;
        pwdat  <= ORIG_VS_ACTIVE -1;
      end
      3'h2: begin
        pwrite <= 1;
        paddr  <= 5'h08;
        pwdat  <= SCAL_HS_ACTIVE -1;
      end
      3'h3: begin
        pwrite <= 1;
        paddr  <= 5'h0C;
        pwdat  <= SCAL_VS_ACTIVE -1;
      end
      3'h4: begin
        pwrite <= 1;
        paddr  <= 5'h10;
//        pwdat  <= (ORIG_VS_ACTIVE>>1)*2048/SCAL_VS_ACTIVE;
        pwdat  <= (ORIG_VS_ACTIVE)*2048/SCAL_VS_ACTIVE;
      end
      3'h5: begin
        pwrite <= 1;
        paddr  <= 5'h14;
        pwdat  <= (ORIG_HS_ACTIVE)*2048/SCAL_HS_ACTIVE;
      end
      3'h6: begin
        pwrite <= 1;
        paddr  <= 5'h18;
        pwdat  <= 1;
      end
      default: begin
        pwrite <= 0;
        paddr  <= 5'h0;
        pwdat  <= 0;
      end
    endcase
  end
end

endmodule
